﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Xml.XPath;

using System.ServiceModel.Syndication;

namespace GeoSyndication.KML
{
    [XmlRoot("kml", Namespace = "http://earth.google.com/kml/2.1/")]
    public class KML21FeedFormatter : SyndicationFeedFormatter, IXmlSerializable
    {
        #region Private Fields

        private string version = "2.1";
        private SyndicationFeed feed;
        
        #endregion

        #region Constructor

        public KML21FeedFormatter()
            : base()
        {
        }

        public KML21FeedFormatter(SyndicationFeed feed)
            : base(feed)
        {
            this.feed = feed;
        }

        #endregion

        #region Public Properties

        public override string Version
        {
            get
            {
                return version;
            }
        }

        #endregion

        #region Public Methods

        public static XmlNamespaceManager CreateNamespaceManager(XPathNavigator navigator)
        {
            XmlNamespaceManager manager = null;
            return manager;
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            throw new NotImplementedException();

        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartDocument();
            writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
            writer.WriteAttributeString("version", this.Version);
            {
                CreateFolder(writer, this.feed);
            }
        }

        public override bool CanRead(System.Xml.XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public override void ReadFrom(System.Xml.XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public override void WriteTo(System.Xml.XmlWriter xtr)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Protected Methods
        
        protected override SyndicationFeed CreateFeedInstance()
        {
            return new SyndicationFeed();
        }

        protected override void SetFeed(SyndicationFeed feed)
        {
            base.SetFeed(feed);
        }
 
        #endregion

        #region Private Methods

        private static XPathNavigator CreateNavigator(XmlReader reader)
        {
            //------------------------------------------------------------
            //	Validate parameter
            //------------------------------------------------------------
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            return (new XPathDocument(reader).CreateNavigator());
        }

        private void CreateFolder(XmlWriter writer, SyndicationFeed feed)
        {
            writer.WriteStartElement("Folder");
            writer.WriteElementString("name", feed.Title.Text);
            writer.WriteElementString("description", feed.Description.Text);
            {
                CreatePlacemarks(writer, this.feed);
            }
            writer.WriteEndElement();
        }

        private void CreatePlacemarks(XmlWriter writer, SyndicationFeed feed)
        {
            foreach (SyndicationItem item in feed.Items)
            {
                writer.WriteStartElement("Placemark");
                writer.WriteElementString("name", item.Title.Text);
                if (item.Content.Type == "text")
                    writer.WriteElementString("description", (item.Content as TextSyndicationContent).Text);
                {
                    CreateGeometry(writer, item);
                }

                writer.WriteEndElement();
            }
        }

        private void CreateGeometry(XmlWriter writer, SyndicationItem item)
        {
            foreach (SyndicationElementExtension ext in item.ElementExtensions)
            {
                writer.WriteStartElement(ext.OuterName);
                {
                    XmlReader reader = ext.GetReader();
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            writer.WriteStartElement(reader.Name);
                            writer.WriteAttributes(reader, false);
                            if (reader.IsEmptyElement)
                                writer.WriteEndElement();
                        }
                        else if (reader.NodeType == XmlNodeType.Text)
                        {
                            writer.WriteString(reader.Value);
                        }
                        else if (reader.NodeType == XmlNodeType.EndElement)
                        {
                            writer.WriteEndElement();
                            break;
                        }
                    }
                    reader.Close();
                }

                writer.WriteEndElement();
            }
        }

        #endregion
    }
}
